/*
 * @CreatDate: 2020-08-31 13:59:35
 * @Describe: 流程图绘制基类
 * 调用此基类的前提需要先引入jQuery,lodash,backbone,joint,当前已在index.html上引入
 *
 * API文档：https://resources.jointjs.com/mmap/joint.html
 * JointJS入门教程：https://resources.jointjs.com/docs/jointjs/v3.2/joint.html
 */

import "./index.less";
import dagre from "dagre";
import graphlib from "graphlib";

class Workflow {
	constructor(el, config) {
		this.config = {
			defaultRouter: "orthogonal", // orthogonal,manhattan,metro,normal
			...config
		};
		this.el = el;
		this.init();
	}

	init() {
		this.graph = new joint.dia.Graph();
		this.keyboard = new joint.ui.Keyboard();
		this.paper = new joint.dia.Paper({
			width: 2000,
			height: 1500,
			model: this.graph,
			defaultLink: new joint.dia.Link({
				markup: [
					'<path class="connection" stroke="#B2BECD" d="M 0 0 0 0"/>',
					'<path class="marker-source" fill="#B2BECD" stroke="#B2BECD" d="M 0 0 0 0"/>',
					'<path class="marker-target" fill="#B2BECD" stroke="#B2BECD" d="M 0 0 0 0"/>',
					'<path class="connection-wrap" d="M 0 0 0 0"/>',
					'<g class="labels" />',
					'<g class="marker-vertices"/>',
					'<g class="marker-arrowheads"/>',
					'<g class="link-tools" />'
				].join(""),
				attrs: {
					".marker-target": { fill: "#B2BECD", d: "M 10 0 L 0 5 L 10 10 z" }
				},
				bpmnType: "SequenceFlow"
			}),
			defaultRouter: {
				name: this.config.defaultRouter
			}
		}).on({
			"blank:pointerdown": (evt, x, y) => {
				if (this.keyboard.isActive("shift ctrl command", evt)) {
					if (this.selection) {
						this.selection.startSelecting(evt, x, y);
					}
				} else {
					if (this.selection) {
						this.selection.cancelSelection();
					}
					this.paperScroller.startPanning(evt, x, y);
				}
			},
			"element:pointerdown": (cellView, evt) => {
				if (this.keyboard.isActive("ctrl meta", evt)) {
					if (this.selection) {
						this.selection.collection.add(cellView.model);
					}
				}
			}
		});
		this.addPaperScroller();
		this.addNavigation();
		this.addCommandManager();
		this.addSnaplines();
		this.elementClick();
	}

	// 渲染数据 cells:[]
	setData(cells) {
		this.graph.clear();
		this.graph.addCells(cells);
	}

	// 获取数据
	getData() {
		return this.graph.toJSON();
	}

	// 单击节点
	elementClick() {
		this.paper.on("cell:pointerclick", (cellView) => {
			// We don't want a Halo for links.
			if (cellView.model instanceof joint.dia.Link) return;
			this.customHalo(cellView);
		});
	}

	customHalo(cellView) {
		let halo = new joint.ui.Halo({
			cellView: cellView,
			boxContent: false,
			clearAll: true
		});

		// 自定义操作面板
		// halo.removeHandle("clone");
		// halo.removeHandle("resize");
		// halo.removeHandle("rotate");
		// halo.removeHandle("fork");
		// halo.removeHandle("unlink");
		// halo.changeHandle("link", { icon: "/joint/img/link.png" });
		// halo.changeHandle("remove", { icon: "/joint/img/remove.png" });

		// halo.on("action:link:add", (link) => {
		// 	console.log("连线成功，可以在此做业务逻辑处理");
		// });
		// halo.on("action:remove:pointerup", () => {
		// 	halo.remove();
		// });

		halo.render();
	}

	// 对画布实现平移，滚动操作
	addPaperScroller() {
		this.paperScroller = new joint.ui.PaperScroller({
			paper: this.paper,
			autoResizePaper: true,
			padding: 0,
			cursor: "pointer"
		});
		this.el.append(this.paperScroller.render().el);
	}

	// 添加小窗口
	addNavigation() {
		this.nav = new joint.ui.Navigator({
			paperScroller: this.paperScroller,
			width: 160,
			height: 120,
			padding: 5,
			zoomOptions: { max: 2, min: 0.2 }
		});
		this.el.append(this.nav.render().el);
	}

	// 拖拽面板
	addStencil(el, stencilItem) {
		this.stencil = new joint.ui.Stencil({
			paper: this.paper
		});
		el.append(this.stencil.render().el);
		this.stencil.load(stencilItem);
		$(".stencil-paper-drag").remove();
	}

	// 操作面板
	addCommandManager() {
		this.commandManager = new joint.dia.CommandManager({
			graph: this.graph,
			cmdBeforeAdd: (cmdName, cell, graph, options) => {
				options = options || {};
				return !options.ignoreCommandManager;
			}
		});
	}

	// 选择插件
	addSelection() {
		this.selection = new joint.ui.Selection({
			paper: this.paper
		});
	}

	// 注册辅助线并开启
	addSnaplines() {
		this.snaplines = new joint.ui.Snaplines({ paper: this.paper });
		this.openSnaplines();
	}

	// 开启辅助线
	openSnaplines() {
		this.snaplines.startListening();
	}

	// 关闭辅助线
	closeSnaplines() {
		this.snaplines.stopListening();
	}

	// 清空画布
	clear() {
		this.graph.clear();
	}

	// 撤销
	undo() {
		this.commandManager.undo();
	}

	// 重做
	redo() {
		this.commandManager.redo();
	}

	// 打印
	print() {
		this.paper.print();
	}

	// openAsSVG
	openAsSVG() {
		this.paper.openAsSVG();
	}

	// 放大
	zoomIn() {
		this.paperScroller.zoom(0.2, { max: 2 });
	}

	// 缩小
	zoomOut() {
		this.paperScroller.zoom(-0.2, { min: 0.2 });
	}

	// 全屏
	fullScreen() {
		const element = document.documentElement;
		if (element.requestFullscreen) {
			element.requestFullscreen();
		} else if (element.msRequestFullscreen) {
			element.msRequestFullscreen();
		} else if (element.mozRequestFullScreen) {
			element.mozRequestFullScreen();
		} else if (element.webkitRequestFullscreen) {
			element.webkitRequestFullscreen();
		}
	}

	// 退出全屏
	exitFullscreen() {
		if (document.exitFullscreen) {
			document.exitFullscreen();
		} else if (document.msExitFullscreen) {
			document.msExitFullscreen();
		} else if (document.mozCancelFullScreen) {
			document.mozCancelFullScreen();
		} else if (document.webkitExitFullscreen) {
			document.webkitExitFullscreen();
		}
	}

	// 美化布局
	// direction of the layout (one of "TB" (top-to-bottom) / "BT" (bottom-to-top) / "LR" (left-to-right) / "RL" (right-to-left))
	beautify(direction) {
		this.paper.freeze();
		joint.layout.DirectedGraph.layout(this.graph, {
			dagre: dagre,
			graphlib: graphlib,
			rankDir: direction,
			rankSep: 80,
			nodeSep: 80,
			edgeSep: 50,
			marginX: 100,
			marginY: 100
		});
		this.paper.unfreeze();
	}

	// 销毁
	destroy() {
		console.log("销毁");
		this.graph.destroy();
		this.paper.remove();
		if (this.stencil) {
			this.stencil.remove();
		}
		this.nav.remove();
		this.paperScroller.remove();
		this.commandManager.destroy();
		if (this.selection) {
			this.selection.remove();
		}
		this.snaplines.remove();
	}

}

export default Workflow;
